package com.heima.service.impl;

import com.heima.component.RedisComponent;
import com.heima.entity.constants.Constants;
import com.heima.entity.dto.SessionShareDto;
import com.heima.entity.dto.UserSpaceDto;
import com.heima.entity.enums.FileFolderTypeEnums;
import com.heima.entity.enums.PageSize;
import com.heima.entity.enums.ResponseCodeEnum;
import com.heima.entity.enums.ShareValidTypeEnums;
import com.heima.entity.po.FileInfo;
import com.heima.entity.po.FileShare;
import com.heima.entity.po.UserInfo;
import com.heima.entity.query.FileInfoQuery;
import com.heima.entity.query.FileShareQuery;
import com.heima.entity.query.SimplePage;
import com.heima.entity.query.UserInfoQuery;
import com.heima.entity.vo.PaginationResultVO;
import com.heima.exception.BusinessException;
import com.heima.mapper.FileInfoMapper;
import com.heima.mapper.FileShareMapper;
import com.heima.mapper.UserInfoMapper;
import com.heima.service.FileShareService;
import com.heima.utils.DateUtil;
import com.heima.utils.StringTools;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 分享信息 业务接口实现
 */
@Service("fileShareService")
public class FileShareServiceImpl implements FileShareService {

    @Resource
    private FileShareMapper<FileShare, FileShareQuery> fileShareMapper;

    @Resource
    private FileInfoMapper<FileInfo,FileInfoQuery> fileInfoMapper;

    @Resource
    private RedisComponent redisComponent;

    @Resource
    private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
    /**
     * 根据条件查询列表
     */
    @Override
    public List<FileShare> findListByParam(FileShareQuery param) {
        return this.fileShareMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(FileShareQuery param) {
        return this.fileShareMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResultVO<FileShare> findListByPage(FileShareQuery param) {
        int count = this.findCountByParam(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

        SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
        param.setSimplePage(page);
        List<FileShare> list = this.findListByParam(param);
        PaginationResultVO<FileShare> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(FileShare bean) {
        return this.fileShareMapper.insert(bean);
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<FileShare> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.fileShareMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<FileShare> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.fileShareMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 根据ShareId获取对象
     */
    @Override
    public FileShare getFileShareByShareId(String shareId) {
        return this.fileShareMapper.selectByShareId(shareId);
    }

    /**
     * 根据ShareId修改
     */
    @Override
    public Integer updateFileShareByShareId(FileShare bean, String shareId) {
        return this.fileShareMapper.updateByShareId(bean, shareId);
    }

    /**
     * 根据ShareId删除
     */
    @Override
    public Integer deleteFileShareByShareId(String shareId) {
        return this.fileShareMapper.deleteByShareId(shareId);
    }

    @Override
    public void saveShare(FileShare share) {
        ShareValidTypeEnums typeEnums = ShareValidTypeEnums.getByType(share.getValidType());
        if (typeEnums == null){
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        if (ShareValidTypeEnums.FOREVER != typeEnums){
            share.setExpireTime(DateUtil.getAfterDate(typeEnums.getDays()));
        }
        Date curDate = new Date();
        share.setShareTime(curDate);
        if (StringTools.isEmpty(share.getCode())){
            share.setCode(StringTools.getRandomString(Constants.LENGTH_5));
        }
        share.setShowCount(0);
        share.setShareId(StringTools.getRandomString(Constants.LENGTH_20));
        fileShareMapper.insert(share);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFileShareBatch(String shareIds, String userId) {
        String[] shareIdArray = shareIds.split(",");
        Integer i = fileShareMapper.deleteFileShareBatch(shareIdArray, userId);
        if (i != shareIdArray.length){
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
    }

    @Override
    public void checkShareCode(HttpSession session,String shareId, String code) {

        FileShare share = fileShareMapper.selectByShareId(shareId);
        if (share == null){
            throw new BusinessException(ResponseCodeEnum.CODE_902);
        }
        if (!code.equals(share.getCode())){
            throw new BusinessException("提取码错误");
        }
        SessionShareDto shareDto = new SessionShareDto();
        fileShareMapper.updateShareShowCount(shareId);
        shareDto.setFileId(share.getFileId());
        shareDto.setShareUserId(share.getUserId());
        shareDto.setExpireTime(share.getExpireTime());
        shareDto.setShareId(shareId);
        session.setAttribute(Constants.SESSION_SHARE_KEY+shareId,shareDto);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savaShare1(String shareId, String shareFileIds, String myFolderId, String shareUserId, String userId) {

        String[] shareFileIdArray = shareFileIds.split(",");
        FileInfoQuery query = new FileInfoQuery();

        //查询目标文件夹所有文件信息
        query.setUserId(userId);
        query.setFilePid(myFolderId);
        List<FileInfo> fileInfos = fileInfoMapper.selectList(query);
        Map<String,FileInfo> fileInfoMap = fileInfos.stream().collect(Collectors.toMap(FileInfo::getFileName, Function.identity(),(data1, data2)->data2));

        //查找所选文件信息
        query = new FileInfoQuery();
        query.setUserId(shareUserId);
        query.setFileIdArray(shareFileIdArray);
        List<FileInfo> infos = fileInfoMapper.selectList(query);

        //保存的文件
        List<FileInfo> CopyList = new ArrayList<>();
        Date curDate = new Date();
        for (FileInfo info : infos) {
            FileInfo file = fileInfoMap.get(info.getFileName());
            if (file != null){
                StringTools.rename(info.getFileName());
            }
            exchangeAllFile(curDate,CopyList,info,myFolderId,shareUserId,userId);
        }
        fileInfoMapper.insertBatch(CopyList);
        //判断使用空间是否满足条件
        Long l = fileInfoMapper.selectUseSpace(userId);
        UserInfo userInfo = userInfoMapper.selectByUserId(userId);
        if (l > userInfo.getTotalSpace()){
            throw new BusinessException(ResponseCodeEnum.CODE_904);
        }
        //更新用户空间
        userInfo.setUseSpace(l);
        userInfoMapper.updateUserTrulySpace(userId,l,null);
        //更新缓存
        UserSpaceDto userSpaceUse = redisComponent.getUserSpaceUse(userId);
        userSpaceUse.setUseSpace(l);
        redisComponent.saveUserSpace(userId,userSpaceUse);


    }

    private void exchangeAllFile(Date curDate,List<FileInfo> copyList,FileInfo fileInfo,String myFolderId,String sourceuserId,String currentUserId){
        String sourceFileId = fileInfo.getFileId();
        String newFileId = StringTools.getRandomString(Constants.LENGTH_10);
        fileInfo.setFileId(newFileId);
        fileInfo.setLastUpdateTime(curDate);
        fileInfo.setFilePid(myFolderId);
        fileInfo.setUserId(currentUserId);
        fileInfo.setCreateTime(curDate);
        copyList.add(fileInfo);

        if (fileInfo.getFolderType() == FileFolderTypeEnums.FOLDER.getType()){
            FileInfoQuery query = new FileInfoQuery();
            query.setFilePid(sourceFileId);
            query.setUserId(sourceuserId);
            List<FileInfo> fileInfos = fileInfoMapper.selectList(query);
            for (FileInfo info : fileInfos) {
                exchangeAllFile(curDate,copyList,info,newFileId,sourceuserId,currentUserId);
            }
        }
    }
}